﻿using System;
using System.IO;
using System.Collections.Generic;
using LibMSNP.MSNPProtocol;
using LibMSNP.HTTP;

namespace Beaup.UnitTests
{
    public class MSNPCommandTester : UnitTester
    {
        #region MSNPCommandFactory

        private class MSNPCommandFactory
        {           
            static MSNPCommandFactory() 
            {
                //_TransactionId = 1;    
            }

            public static IMSNPCommand CreateCommand(string commandString)
            {
                IMSNPCommand cmd = null;
                string payload = string.Empty;

                string[] lines = commandString.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                string[] commandParts = lines[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                string[] parameters = new string[commandParts.Length - 2];

                for (int i = 1; i < lines.Length; i++)
                    payload += lines[i];

                for (int i = 2, j = 0; i < commandParts.Length; i++, j++)
                    parameters[j] = commandParts[i];

                HTTPRequestHeader header = new HTTPRequestHeader("POST", "gateway");
                cmd = new MSNPCommand(commandParts[0], int.Parse(commandParts[1]), header, payload, parameters);
                
                return cmd;
            }
        }

        #endregion

        private LinkedList<IMSNPCommand> _commands;

        public MSNPCommandTester()
        {
            string name  = ((object)this).GetType().Name + ".tfl";
            _unitTestFile = new FileInfo(name);
            _errors = new LinkedList<UnitError>();
            _commands = new LinkedList<IMSNPCommand>();
        }

        public override void RunTest()
        {
            StreamReader reader = null;
            int lineNo = 0;
            string command = string.Empty;
            MSNPCommand cmd = null;
            try
            {
                reader = _unitTestFile.OpenText();

                while (true)
                {
                    if (reader.EndOfStream)
                        break;
                    string ln = reader.ReadLine();
                    ln = ln.Replace("\\r\\n", "\r\n");
                    lineNo++;
                    if (ln == "--##")
                    {
                        try
                        {
                            _commands.AddLast(MSNPCommandFactory.CreateCommand(command));
                            command = string.Empty;
                        }
                        catch (Exception)
                        {
                            _errors.AddLast(new UnitError(lineNo, cmd.ToString()));
                            _passed = false;
                        }
                    }
                    else
                    {
                        command += ln;  
                    }
                }
            }
            catch (FileNotFoundException ex)
            {
                string[] fileName = ex.FileName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
                string directory = string.Empty;
                for (int i = 0; i < fileName.Length - 1; i++)
                {
                    if (i > 0)
                        directory += "\\" + fileName[i];
                    else
                        directory = fileName[i];
                }
                Debug.PrintMessage("Please create a unit test file called: " + fileName[fileName.Length - 1]);
                Debug.PrintMessage("In: " + directory);
            }
            catch (IOException e)
            {
                string name  = ((object)this).GetType().Name;
                Debug.PrintMessage("Error During " + name + " testing.");
                Debug.PrintMessage("Message: " + e.Message);
                Debug.PrintMessage("At " + e.Source);
            }

            finally
            {
                if (reader != null)
                    reader.Close();    
            }
        }

        public override void PrintErrors()
        {
            if (!_passed)
            {
                foreach (UnitError item in _errors)
                {
                    Debug.PrintMessage(item.ToString());
                    Debug.PrintMessage("UnitTest Failed");
                }
            }
            else
            {
                Debug.PrintMessage("UnitTest Passed");
            }
        }

        public override void PrintResults()
        {
            foreach (MSNPCommand item in _commands)
            {
                Debug.PrintMessage(item.ToString());
            }
        }
    }
}
